#include "StdAfx.h"
#include "CurrentTimes.h"
#include "Utilities.h"


CurrentTimes::CurrentTimes(void)
    : m_week(0)
    , m_initday(0)
{
    memset(&m_start, 0, sizeof(m_start));
    memset(&m_lastDate, 0, sizeof(m_lastDate));
    for (int i=0; i<7; i++)
    {
        m_days[i] = 0;
    }
}


CurrentTimes::~CurrentTimes(void)
{
}


int CurrentTimes::ReadCurrent(const BYTE* current)
{
    short* values = (short*)current;
    m_week = 0;
    for (int i=0; i<7; i++)
    {
        m_days[i] = *values++;
        m_week += m_days[i];
    }
    DWORD* val = (DWORD*)values;
    m_lastDate.dwLowDateTime = *val++;
    m_lastDate.dwHighDateTime = *val++;
    return ((BYTE*)val - current);
}


int CurrentTimes::SaveCurrent(BYTE* current)
{
    short* values = (short*)current;
    for (int i=0; i<7; i++)
        *values++ = m_days[i];
    DWORD* val = (DWORD*)values;
    *val++ = m_lastDate.dwLowDateTime;
    *val++ = m_lastDate.dwHighDateTime;
    return ((BYTE*)val - current);
}


void CurrentTimes::InitDate(SYSTEMTIME& st)
{
	int weekDay = Day(st);

    // check if we are a new day and is yes reset today's counter
    ULARGE_INTEGER last_ui;
    last_ui.LowPart = m_lastDate.dwLowDateTime;
    last_ui.HighPart = m_lastDate.dwHighDateTime;
	int last = (int)(last_ui.QuadPart / (10i64*1000*1000*60*60*24));
    // conversions
    FILETIME ft;
    SystemTimeToFileTime(&st, &ft);
    ULARGE_INTEGER ui;
    ui.LowPart = ft.dwLowDateTime;
    ui.HighPart = ft.dwHighDateTime;
	int now = (int)(ui.QuadPart / (10i64*1000*1000*60*60*24));

	switch (now-last)
	{
	default:
		// more than a week without PC!
		m_days[(weekDay-6+7)%7] = 0;
	case 6:
		// 6 days without PC
		m_days[(weekDay-5+7)%7] = 0;
	case 5:
		// 5 days without PC
		m_days[(weekDay-4+7)%7] = 0;
	case 4:
		// 4 days without PC
		m_days[(weekDay-3+7)%7] = 0;
	case 3:
		// 3 days without PC
		m_days[(weekDay-2+7)%7] = 0;
	case 2:
		// 2 days without PC
		m_days[(weekDay-1+7)%7] = 0;
	case 1:
		// we changed one day, reset today's counter
		m_days[weekDay] = 0;
	case 0:
		// we are the same day, do nothing
		break;
	}

    m_start.LowPart = ft.dwLowDateTime;
    m_start.HighPart = ft.dwHighDateTime;
    m_initday = m_days[Day(st)];
    m_week = 0;
    for (int i=0; i<7; i++)
    {
        m_week += m_days[i];
    }
}


void CurrentTimes::UpdateTimes(SYSTEMTIME& st, int interval)
{
    ULARGE_INTEGER last_ui;
    last_ui.LowPart = m_lastDate.dwLowDateTime;
    last_ui.HighPart = m_lastDate.dwHighDateTime;
    // conversions
    FILETIME ft;
    SystemTimeToFileTime(&st, &ft);
    ULARGE_INTEGER ui;
    ui.LowPart = ft.dwLowDateTime;
    ui.HighPart = ft.dwHighDateTime;
    ULONGLONG rel = ui.QuadPart - last_ui.QuadPart;
    rel /= 10*1000;             // now rel is in millisec
    if (rel > interval)
        rel = rel - interval;
    else
        rel = interval - rel;
    if (rel > interval)
    {
        // we were stopped by hibernate or sleep mode, reset all
        InitDate(st);
    }
    rel = ui.QuadPart - m_start.QuadPart;
    rel /= 10*1000*1000*60;    // now rel is in minutes
    if (rel < (24*60))
    {
        int day = Day(st);
        m_days[day] = m_initday + (UINT)rel;
        m_week = 0;
        for (int i=0; i<7; i++)
            m_week += m_days[i];
    }
    m_lastDate.dwLowDateTime = ft.dwLowDateTime;
    m_lastDate.dwHighDateTime = ft.dwHighDateTime;
}
